`ifndef PROCESSING_UNIT
`define PROCESSING_UNIT

module processing_unit #(
	`include "C:/Users/gaoji/Desktop/RISC_SPM/src/para_def.v"
)(
	output [WORD_WD -1:0] instruction	,//to ctl
	output 			      zero_flag     ,//to ctl
	
	output [ADDR_WD -1:0] addr			,//to mem, address
	output [WORD_WD -1:0] bus1			,//to mem, data_in
	
	input  [WORD_WD -1:0] mem_word		,//from mem, data_out
	input  				  load_R0, load_R1, load_R2, load_R3,
	input				  load_PC, 
	input				  load_IR,
	input				  load_reg_Y,
	input				  load_reg_Z,
	input				  load_add_R,
	input				  inc_PC,
	input  [SEL1_WD -1:0] mux1_sel_to_bus1,
	input  [SEL2_WD -1:0] mux2_sel_to_bus2,
	input 				  clk, rst_n
);

	wire [WORD_WD -1:0]   bus2;
	wire [WORD_WD -1:0]   R0_out, R1_out, R2_out, R3_out;
	wire [WORD_WD -1:0]   alu_out;
	wire [WORD_WD -1:0]   Y_out;
	wire [WORD_WD -1:0]	  PC_out;
	wire 				  alu_zero_flag;	
	wire [OPCODE_WD -1:0] opcode;

	assign opcode = instruction[(WORD_WD -1) : (WORD_WD -OPCODE_WD)];
	
	reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R0(.data_out(R0_out), .data_in(bus2), .load(load_R0), .clk(clk), .rst_n(rst_n));
	reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R1(.data_out(R1_out), .data_in(bus2), .load(load_R1), .clk(clk), .rst_n(rst_n));
	reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R2(.data_out(R2_out), .data_in(bus2), .load(load_R2), .clk(clk), .rst_n(rst_n));
	reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_R3(.data_out(R3_out), .data_in(bus2), .load(load_R3), .clk(clk), .rst_n(rst_n));
	
	reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_REG_Y(.data_out(Y_out), .data_in(bus2), .load(load_reg_Y), .clk(clk), .rst_n(rst_n));	
	reg_unit #(.WORD_WD(1))       U_REG_Z(.data_out(zero_flag), .data_in(alu_zero_flag), .load(load_reg_Z), .clk(clk), .rst_n(rst_n));
	reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_IR(.data_out(instruction), .data_in(bus2), .load(load_IR), .clk(clk), .rst_n(rst_n));
	reg_unit #(.WORD_WD(WORD_WD), .DISPLAY_EN(1)) U_ADD_R(.data_out(addr), .data_in(bus2), .load(load_add_R), .clk(clk), .rst_n(rst_n));
	
	program_count #(.WORD_WD(WORD_WD)) U_PC(.count_out(PC_out), .count_in(bus2), .load(load_PC), .incr(inc_PC), .clk(clk), .rst_n(rst_n));

	mux_5sel1 #(.WORD_WD(WORD_WD), .SEL1_WD(SEL1_WD)) U_MUX1(
		.mux_out(bus1), 
		.mux_in0(R0_out), 
		.mux_in1(R1_out), 
		.mux_in2(R2_out), 
		.mux_in3(R3_out),
		.mux_in4(PC_out),
		.sel(mux1_sel_to_bus1)
	);
	
	mux_3sel1 #(.WORD_WD(WORD_WD), .SEL1_WD(SEL2_WD)) U_MUX2(
		.mux_out(bus2), 
		.mux_in0(alu_out), 
		.mux_in1(bus1), 
		.mux_in2(mem_word), 
		.sel(mux2_sel_to_bus2)
	);
	
	alu_unit #(.WORD_WD(WORD_WD), .OPCODE_WD(OPCODE_WD)) U_ALU(
		.alu_out(alu_out),
		.zero_flag(alu_zero_flag),
		.alu_in1(Y_out),
		.alu_in2(bus1),
		.opcode(opcode)
	);
endmodule//: processing_unit

`endif